iT邦幫忙

2024 iThome 鐵人賽

DAY 12
1
JavaScript

可愛又迷人的 Web API系列 第 12

Day12. 用 Audio 和 Video API 打造自己的影音平台 II

  • 分享至 

  • xImage
  •  

上一篇跟大家介紹了 Audio API,使用的是 <audio> 標籤,今天要介紹的是 Video API,不難發現使用的標籤就是 <video> XXD,那 Video API 又有哪些好用的功能呢?

Video 標籤與 API

<video> 基本的功能跟 <audio> 蠻像的,我們同樣可以控制影片的播放、暫停、跳轉時間,調整音量 ... 等等

播放和暫停

使用 play()pause() 來播放與暫停影片,此外還能使用 currentTime 修改跳轉的影片位置

<video src="video.mp4" controls></video>
const video = document.querySelector('video');
video.play();  // 播放
video.pause(); // 暫停
video.currentTime = 30; // 跳轉到第30秒

切換影片

我們可以使用 load() 來動態切換影片:

video.src = 'https://example.com/video.mp4';
video.load(); // 載入新的影片

調整音量

調整音量也是不可少的功能 XD,還能一鍵靜音!

video.volume = 0.5; // 調整音量為 50%
video.muted = true; // 一鍵靜音

顯示影片字幕

使用 <track> 設定字幕檔案位置,目前接受的是 WebVTT(Web Video Text Tracks Format) 格式,副檔名為 .vtt,特別注意的是字幕檔案的編碼必須為 UTF-8 唷。

VTT 字幕檔案結構

VVT 檔案第一行必須寫 WEBVTT,表示這是一個 Web Video Text Tracks 的檔案。

以下是一個字幕檔範例:

WEBVTT

00:00:00.000 --> 00:00:02.000
你好,

00:00:02.500 --> 00:00:05.000
我是 MUKI。
很高興認識你。

與字幕有關的 block 是由三個部分組成:時間戳,字幕內容和空行:

  • 時間戳格式:開始時間 ---> 結束時間
  • 時間格式:小時:分鐘:秒.毫秒,例如 00:00:02.500 表示 2.5 秒

字幕內容可以是單行,也可以是多行,字幕支援基本的 HTML 標記,例如 <b><i>。字幕與字幕之間,要用一個斷行做區隔。

如果要在影片裡使用字幕檔,程式碼要改用 <source> 載入影片檔,使用 <track> 載入字幕檔案:

<video controls>
    <source src="video.mp4" type="video/mp4">
    <track kind="subtitles" src="subtitles.vtt" srclang="en" label="English" default>
</video>
屬性 介紹
kind="subtitles" 表示這是字幕軌
src="subtitles.vtt" 字幕檔案的位置
srclang="en" 字幕檔案的語言
label="English" 在影片播放器的字幕選單中顯示的標籤
default 字幕默認開啟

修改字幕樣式

我們也能在字幕裡寫 CSS 調整字幕的樣式,CSS 樣式必須寫在 WEBVTT 段落的後面,所有 block 的前面,像這樣:

WEBVTT

STYLE
::cue {
  background: #FFF;
  color: #ABCDEF;
}

00:00:00.000 --> 00:00:02.000
你好,

00:00:02.500 --> 00:00:05.000
我是 MUKI。
很高興認識你。

打開影片後,就能看到字幕的顏色改為 #ABCDEF

https://mukiwu.github.io/web-api-demo/img/11-4.png

如果希望這兩段字幕的顏色不同,可以幫他們加入 HTML 標籤 (如 <c><i><b><u><ruby><rt><v> 和 <lang> ) 來調整樣式

WEBVTT

STYLE
::cue {
  color: #ABCDEF;
}

STYLE
::cue(b) {
  color: #D40000;
}

00:00:00.000 --> 00:00:02.000
<b>你好,</b>

00:00:02.500 --> 00:00:05.000
我是 MUKI。
很高興認識你。

使用 <b> 標籤來調整文字顏色為紅色,字幕的「你好」兩個字就會變成紅色

https://mukiwu.github.io/web-api-demo/img/11-5.png

製作多語系的字幕

假設影片有中文和英文兩個語系,我們先做兩個字幕檔

subtitle-zh.vtt

WEBVTT

STYLE
::cue {
  color: #ABCDEF;
}

STYLE
::cue(b) {
  color: #D40000;
}

00:00:00.000 --> 00:00:02.000
<b>你好,</b>

00:00:02.500 --> 00:00:05.000
我是 MUKI。
很高興認識你。

subtitle-en.vtt

WEBVTT

STYLE
::cue {
  color: #ABCDEF;
}

STYLE
::cue(b) {
  color: #D40000;
}

00:00:00.000 --> 00:00:02.000
<b>Hello,</b>

00:00:02.500 --> 00:00:05.000
I am MUKI, Nice to meet you.

接著在 HTML 寫入兩個 <track>,設定字幕檔的位置以及讓使用者識別的文字 (label)

<video controls>
  <source src="video.mp4" type="video/mp4">
  <track kind="subtitles" src="subtitle-en.vtt" srclang="en" label="English">
  <track kind="subtitles" src="subtitle-zh.vtt" srclang="zh" label="中文">
</video>

載入影片後,點選右下角的「⋮」,就能選擇字幕了

https://mukiwu.github.io/web-api-demo/img/11-6.gif

自定影片播放介面

和 Audio API 相同,我們也能客製化影片播放的介面,首先一樣將 controls 移除,接著使用跟上一篇文章相同的方式打造自己的介面

<!-- 將 <video controls> 改為 <video> -->
<video>
  <source src="video.mp4" type="video/mp4">
</video>

自訂滑動桿

其實 <audio><video> 的方法很像,我也是從自定義音樂播放介面改過來的,就直接貼上所有的 javascript 給大家參考:

// 獲取 DOM 元素
const video = document.getElementById('video');
const currentTime = document.getElementById('currentTime');
const duration = document.getElementById('duration');
const range = document.getElementById("range");

const playButton = document.getElementById('playPause');

const updateVar = (value) => {
  document.documentElement.style.setProperty("--range", value + "%");
}
range.addEventListener("input", () => {
  updateVar(range.value);
});

// 播放/暫停功能
function togglePlay() {
  if (video.paused) {
    video.play();
    playButton.textContent = '暫停';
  } else {
    video.pause();
    playButton.textContent = '播放';
  }
}

// 根據滑動桿的值設置視頻的當前時間
function setVideoProgress() {
  const newTime = (range.value / 100) * video.duration;
  video.currentTime = newTime;
  updateTime();
}

// 更新時間
function updateTime() {
  const currentMinutes = Math.floor(video.currentTime / 60);
  const currentSeconds = Math.floor(video.currentTime % 60);
  const durationMinutes = Math.floor(video.duration / 60);
  const durationSeconds = Math.floor(video.duration % 60);

  currentTime.textContent = `${currentMinutes}:${currentSeconds.toString().padStart(2, '0')}`;
  duration.textContent = `${durationMinutes}:${durationSeconds.toString().padStart(2, '0')}`;
}

// 更新滑動桿
function updateRange() {
  const rangeValue = (video.currentTime / video.duration) * 100;
  range.value = rangeValue;
  updateVar(rangeValue);
}

playButton.addEventListener('click', togglePlay);
video.addEventListener('timeupdate', () => {
  updateTime();
  updateRange();
});

video.addEventListener('loadedmetadata', () => {
  updateTime();
});

range.addEventListener('input', setVideoProgress);

自訂子母畫面

子母畫面 (picture-in-picture) 真是一個偉大的發明,我自己就很喜歡使用子母畫面邊工作邊看影片,可以放鬆一下又不會太墮落 XD,適合可以一心二用的我們!

先增加一個子母畫面的按鈕

<button id="pipButton">子母畫面</button>

togglePiP() 負責切換子母畫面。

async function togglePiP() {
  try {
    if (video !== document.pictureInPictureElement) {
      await video.requestPictureInPicture();
    } else {
      await document.exitPictureInPicture();
    }
  } catch (error) {
    console.error(error);
  }
}

pipButton.addEventListener('click', togglePiP);

唯一要注意的是,只有支援 Picture-in-Picture API 的瀏覽器才能使用,例如 Chrome 和 Edge,而 Firefox 目前尚未支援(來源文件:MDN)

影片緩衝

如果影片檔案太大或網路速度不好,在播放影片時斷斷續續的,體驗就不會好。我們可以使用相關的緩衝事件,來提升影片播放的流暢度

video.addEventListener('waiting', () => {
  console.log('緩衝中...');
});

video.addEventListener('canplay', () => {
  console.log('可以播放');
});

// 檢查緩衝進度
setInterval(() => {
  const buffered = video.buffered;
  if (buffered.length > 0) {
      const bufferedEnd = buffered.end(buffered.length - 1);
      console.log(`已緩衝 ${bufferedEnd} 秒`);
  }
}, 1000);

未來也能透過緩衝的秒數,製作進度條讓使用者知道目前緩衝的狀況

https://mukiwu.github.io/web-api-demo/img/11-6.png

程式碼範例

程式碼範例網址:https://mukiwu.github.io/web-api-demo/video.html

小結

對以上文章有任何問題歡迎留言討論唷。


上一篇
Day11. 用 Audio 和 Video API 打造自己的影音平台 I
下一篇
Day13. 使用 Web Workers API 走出自己的路
系列文
可愛又迷人的 Web API31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
connieleung
iT邦新手 5 級 ‧ 2024-09-20 08:00:56

大神

MUKIwu iT邦新手 5 級 ‧ 2024-09-27 07:26:32 檢舉

謝謝你不嫌棄 ^Q^

我要留言

立即登入留言